<?php defined('SYSPATH') or die('No direct script access.');

class Arr extends Kohana_Arr {
	
	public static function explode($string, $separator = '|')
	{
		$string = trim($string, $separator);
		return explode($separator, $string);
	}
	
	public static function implode(array $array = array(), $separator = '|', $wrap = FALSE)
	{
		$string = implode($separator, $array);
		$string = trim($string, $separator);
		
		if ($wrap === TRUE)
			$string = $separator . $string . $separator;
		
		return $string;
	}
	
	/**
	 * Подготовка массива для вывода в таблицу.
	 *
	 * Предположим, что позиции каталога требуется вывести по несколько позиций
	 * в строку и сверстать их таблицей. При итерации по обычному массиву возникают
	 * трудности для определения мест, в которых требуется вывести <tr>, </tr>,
	 * а также необходимо правильно заполнить последнюю строку ячейками (если длины
	 * массива недостаточно).
	 *
	 * Гораздо удобнее иметь массив, который будет состоять как из "строк,
	 * так и из "ячеек".
	 *
	 * Пример:
	 *
	 * Есть массив $array:
	 *
	 * array(
	 *	 [0] => array( [id] => 1 )
	 *	 [0] => array( [id] => 2 )
	 *	 [0] => array( [id] => 3 )
	 *	 [0] => array( [id] => 4 )
	 *	 [0] => array( [id] => 5 )
	 * )
	 *
	 * Сконвертируем массив:
	 * $array = Arr::convert_for_table($array, 2);
	 *
	 * array(
	 *	 [0] => array(
	 *		 [0] => array( [id] => 1 )
	 *		 [1] => array( [id] => 2 )
	 *	 )
	 *	 [1] => array(
	 *		 [0] => array( [id] => 3 )
	 *		 [1] => array( [id] => 4 )
	 *	 )
	 *	 [2] => array(
	 *		 [0] => array( [id] => 5 )
	 *		 [1] => array()
	 *	 )
	 * )
	 *
	 * @param array $array	Исходный массив
	 * @param integer $cols_num	Необходимое число колонок в таблице
	 * @return array
	 */
	public static function convert_for_table($array, $cols_num)
	{
		$result = array();

		if ( ! empty($array) AND is_array($array))
		{
			$k = 0;
			$e = 0;

			foreach ($array as $value)
			{
				$result[$k][$e] = $value;
				$k = $e == $cols_num - 1 ? $k + 1 : $k;
				$e = $e == $cols_num - 1 ? 0 : $e + 1;
			}

			if (count($result[count($result) - 1]) < $cols_num)
			{
				for ($i = count($result[count($result) - 1]); $i < $cols_num; $i++)
				{
					$result[count($result) - 1][] = array();
				}
			}
		}

		return $result;
	}

	/**
	 * Генерирование многомерного дверовидного массива на основе исходного.
	 *
	 * @param array $array	Исходный массив
	 * @param string $value_key	Ключ, на основе которого следует пересоздать ключи массива для обработки
	 *	 array[0] = array('id' => 1, 'path' => '/about');
	 *   array[1] = array('id' => 2, 'path' => '/contacts');
	 * 
	 * Если $value_key равен 'path', то массив переформируется в
	 *   array[about] = array('id' => 1, 'path' => '/about');
	 *   array[contacts] = array('id' => 2, 'path' => '/contacts');
	 * 
	 * @return bool|array
	 */
	public static function build_level_tree($array, $value_key, $delimiter = "/")
	{
		if (!is_array($array))
			return FALSE;

		// регулярное выражение для формирования дерева
		$splitRE = "/" . addcslashes($delimiter, "/\-_ ") . "/";

		// исходное пустое дерево
		$tree = array();

		// меняем ключи у исходного массива
		$array_mod_keys = array();

		while (list($key, $val) = each($array))
		{
			$array_mod_keys[$val[$value_key]] = $val;
		}

		// заменяем исходный массив новым (с обновлёнными ключами)
		$array = $array_mod_keys;

		unset($array_mod_keys);

		// формируем дерево
		foreach ($array as $key => $val)
		{
			// определяем родительские ($parts)и текущий ($leafPart) сегменты
			$parts = preg_split($splitRE, $key, -1, PREG_SPLIT_NO_EMPTY);
			$leafPart = array_pop($parts);

			// построение родительской структуры (для очень глубоких структур может работать медленно)
			$parentArr = &$tree;

			foreach ($parts as $part)
			{
				if ( ! isset($parentArr[$part]))
				{
					$parentArr[$part] = array();
				}
				elseif (!is_array($parentArr[$part]))
				{
					$parentArr[$part] = array();
				}
				if ( ! empty($parentArr[$part]))
				{
					$parentArr = &$parentArr[$part]['child_nodes'];
				}
			}

			// добавление финального сегмента в структуру
			if (empty($parentArr[$leafPart]))
			{
				$parentArr[$leafPart] = $val;
			}
		}

		// удаляем пустые элементы
		foreach ($tree as $k => $val)
		{
			if (empty($val))
				unset($tree[$k]);
		}

		// возвращаем сгенерированный результат
		return $tree;
	}

	/**
	 * Генерирование многомерного дверовидного массива на основе исходного.
	 * Генерация производится по ключу, определяющему родителя.
	 *
	 * @param array $array	Исходный массив
	 * @param string $id_key
	 * @param string $parent_key	Ключ, на основе которого следует строить дерево, ключи элементов пересоздаются
	 *															 array[0] = array('id' => 1, 'parent' => 0);
	 *															 array[1] = array('id' => 2, 'parent' => 3);
	 * 								 array[2] = array('id' => 3, 'parent' => 0);
	 *													 Если $id_key равен 'id', а $parent_key равен 'parent', то массив переформируется в
	 *															 array[1] = array('id' => 1, 'parent' => 0);
	 *															 array[3] = array(
	 * 											'id' => 3,
	 * 											'parent' => 0,
	 * 											'child_nodes' => array(
	 * 												2 => array(
	 * 													'id' => 2,
	 * 													'parent' => 3,
	 * 												),
	 * 											),
	 * 										);
	 * 		На корневом уровне дерева остаются элементы, для которых не найдены родители, либо $parent_key == $id_key
	 * @return bool|array
	 */
	public static function build_array_tree($array, $id_key, $parent_key)
	{
		if (!is_array($array))
			return FALSE;

		// исходное пустое дерево
		$tree = array();

		// меняем ключи у исходного массива
		$array_mod_keys = array();

		while (list($key, $val) = each($array))
		{
			$array_mod_keys[$val[$id_key]] = $val;
		}

		// заменяем исходный массив новым (с обновлёнными ключами)
		$array = $array_mod_keys;
		unset($array_mod_keys);

		// формируем дерево
		foreach ($array as $key => $val)
		{
			// задача 1: найти родителей элемента до корня, если таковые есть
			$parents = array();

			if ($val[$id_key] != $val[$parent_key])
			{
				$parent_key_arr = Arr::select($array, $id_key, $val[$parent_key]);
				while ( ! empty($parent_key_arr))
				{
					$parents[] = $parent_key_arr[0][$id_key];
					if ($parent_key_arr[0][$id_key] == $parent_key_arr[0][$parent_key])
						break;
					$parent_key_arr = Arr::select($array, $id_key, $parent_key_arr[0][$parent_key]);
				}
			}

			$parents = array_reverse($parents);

			// построение родительской структуры (для очень глубоких структур может работать медленно)
			$parentArr = &$tree;

			if ( ! empty($parents))
			{
				foreach ($parents as $parent)
				{
					if ( ! isset($parentArr[$parent]))
					{
						$parentArr[$parent] = array();
					}
					elseif (!is_array($parentArr[$parent]))
					{
						$parentArr[$parent] = array();
					}
					if (isset($parentArr[$parent]))
					{
						$parentArr = &$parentArr[$parent]['child_nodes'];
					}
				}
			}

			// добавление финального сегмента в структуру
			if (empty($parentArr[$val[$id_key]]))
			{
				$parentArr[$val[$id_key]] = $val;
			}
			else
			{
				foreach ($val as $col_key => $col_val)
				{
					$parentArr[$val[$id_key]][$col_key] = $col_val;
				}
			}
		}

		// удаляем пустые элементы
		foreach ($tree as $k => $val)
		{
			if (empty($val))
				unset($tree[$k]);
		}

		// возвращаем сгенерированный результат
		return $tree;
	}

	/**
	 * Выборка массива из массива в соответствии с заданными уловиями.
	 *
	 * ПРИМЕР ИСПОЛЬЗОВАНИЯ
	 *
	 * Имеем массив $users_roles:
	 *
	 * array
	 *	 0 =>
	 *		 array
	 *			 'name' => string 'guest' (length=5)
	 *			 'permission' => string 'view' (length=4)
	 *	 1 =>
	 *		 array
	 *			'name' => string 'user' (length=4)
	 *			'permission' => string 'view' (length=4)
	 *	 2 =>
	 *		 array
	 *			 'name' => string 'admin' (length=5)
	 *			 'permission' => null
	 *
	 * Получаем массив с name равным guest или user:
	 *
	 * $users_roles = Arr::select($users_roles, 'name', array('guest', 'user'));
	 *
	 * array
	 *	 0 =>
	 *		 array
	 *			 'name' => string 'guest' (length=5)
	 *			 'permission' => string 'view' (length=4)
	 *	 1 =>
	 *		 array
	 *			'name' => string 'user' (length=4)
	 *			'permission' => string 'view' (length=4)
	 *
	 * @param array $array
	 * @param string $col
	 * @param string|integer $values
	 * @paramm bool $preserve_keys
	 * @return array
	 */
	public static function select($array, $col = NULL, $values = NULL, $preserve_keys = FALSE)
	{
		if (is_array($array) AND ! empty($array))
		{
			if ($col !== NULL AND $values !== NULL)
			{
				$result = array();

				if (!is_array($values))
				{
					$values = array($values);
				}

				foreach ($array as $key => $row)
				{
					if (is_array($row) AND ! empty($row) AND isset($row[$col]) AND in_array($row[$col], $values))
					{
						if ($preserve_keys === TRUE)
						{
							$result[$key] = $row;
						} else
							$result[] = $row;
					}
				}

				return $result;
			}

			return array();
		}

		return array();
	}

	/**
	 * Выборка из массива, только выбираются значения, которые НЕ СООТВЕТСТВУЮТ заданным условиям.
	 *
	 * @param array $array
	 * @param string $col
	 * @param string|integer $values
	 * @return array
	 */
	public static function select_without($array, $col, $values, $preserve_keys = FALSE)
	{
		if (is_array($array) AND ! empty($array))
		{
			if ($col !== NULL AND $values !== NULL)
			{
				$result = array();

				if (!is_array($values))
				{
					$values = array($values);
				}

				foreach ($array as $key => $row)
				{
					if (is_array($row) AND ! empty($row) AND isset($row[$col]) AND ! in_array($row[$col], $values))
					{
						if ($preserve_keys === TRUE)
						{
							$result[$key] = $row;
						} else
							$result[] = $row;
					}
				}

				return $result;
			}

			return array();
		}

		return array();
	}

	/**
	 * Выборка заданной строки массива.
	 *
	 * @param array $array
	 * @param integer $row
	 * @return array
	 */
	public static function select_row($array, $row = NULL)
	{
		if (is_array($array) AND ! empty($array))
		{
			if ($row === NULL)
			{
				$row = reset(array_keys($array));
			}
			if (isset($array[$row]))
			{
				return $array[$row];
			}

			return array();
		}

		return array();
	}

	/**
	 * Получение двумерного массива из исходного путём выборки значения заданной колонки.
	 *
	 * ПРИМЕР ИСПОЛЬЗОВАНИЯ
	 *
	 * Имеем масив $users_roles:
	 *
	 * array
	 *	 0 =>
	 *		 array
	 *			 'name' => string 'guest' (length=5)
	 *			 'permission' => string 'view' (length=4)
	 *	 1 =>
	 *		 array
	 *			'name' => string 'user' (length=4)
	 *			'permission' => string 'view' (length=4)
	 *	 2 =>
	 *		 array
	 *			 'name' => string 'admin' (length=5)
	 *			 'permission' => null
	 *
	 * В результате $users_roles = Arr::select_col($users_roles, name) получим одномерный массив:
	 *
	 * array
	 *	 0 => string 'guest' (length=5)
	 *	 1 => string 'user' (length=4)
	 *	 2 => string 'admin' (length=5)
	 *
	 * @param array $array
	 * @param integer $col
	 * @param bool $preserve_keys
	 * @return array
	 */
	public static function select_col($array, $col = NULL, $preserve_keys = FALSE)
	{
		if (is_array($array) AND ! empty($array))
		{
			$result = array();

			foreach ($array as $key => $row)
			{
				if (is_array($row) AND ! empty($row))
				{
					if ($col === NULL)
					{
						$col = reset(array_keys($row));
					}
					if ($preserve_keys === TRUE)
					{
						$result[$key] = $row[$col];
					} else
						$result[] = $row[$col];
				}
			}

			return $result;
		}

		return array();
	}

	/**
	 * Выборка одной ячейки из массива.
	 *
	 * ПРИМЕР ИСПОЛЬЗОВАНИЯ
	 *
	 * Имеем масив $users_roles:
	 *
	 * array
	 *	 0 =>
	 *		 array
	 *			 'name' => string 'guest' (length=5)
	 *			 'permission' => string 'view' (length=4)
	 *	 1 =>
	 *		 array
	 *			'name' => string 'user' (length=4)
	 *			'permission' => string 'view' (length=4)
	 *	 2 =>
	 *		 array
	 *			 'name' => string 'admin' (length=5)
	 *			 'permission' => null
	 *
	 * Возможные результаты применения:
	 *
	 * echo Arr::select_cell($users_roles);										 // guest
	 * echo Arr::select_cell($users_roels, NULL, NULL);				 // guest
	 * echo Arr::select_cell($users_roles, 0, 'name');					// guest
	 * echo Arr::select_cell($users_roles, 0, 'permission');		// view
	 *
	 * echo Arr::select_cell($users_roles, 1, 'name');					// user
	 * echo Arr::select_cell($users_roles, 1, 'permission');		// view
	 *
	 * echo Arr::select_cell($users_roles, 2);									// admin
	 * echo Arr::select_cell($users_roles, 2, 'permission');		// null
	 *
	 * @param array $array
	 * @param integer $row
	 * @param integer $col
	 * @return mixed
	 */
	public static function select_cell($array, $row = NULL, $col = NULL)
	{
		if (is_array($array) AND ! empty($array))
		{
			if ($row === NULL)
			{
				$row = reset(array_keys($array));
			}
			if ($col === NULL)
			{
				$col = reset($array[$row]);
			}
			if (isset($array[$row][$col]))
			{
				return $array[$row][$col];
			}

			return NULL;
		}

		return NULL;
	}

	/**
	 * Получение нужного значение из массива.
	 *
	 * Например, есть массив характеристик для позиции каталога:
	 *
	 * (array) Array
	 * (
	 *		 [0] => Array
	 *				 (
	 *						 [meta_caption] => Артикул
	 *						 [value_text] => DV16VSS
	 *				 )
	 *		 [1] => Array
	 *				 (
	 *						 [meta_caption] => Цена
	 *						 [value_text] => 2900.00
	 *				 )
	 *		 [2] => Array
	 *				 (
	 *						 [meta_caption] => Вес
	 *						 [value_text] => 1.50
	 *				 )
	 *		 [3] => Array
	 *				 (
	 *						 [meta_caption] => Количество
	 *						 [value_text] =>
	 *				 )
	 * )
	 *
	 * Допустим, из этого массива нужно получить цену продукта. Теперь всё просто:
	 *
	 * // запишем в переменную $price значение 2900.00
	 * $price = Arr::select_related_cell($array, 'meta_caption', 'Цена', 'value_text');
	 *
	 * @param array $array Многомерный исходный массив
	 * @param mixed $related_key Ключ, по которому будет искаться "строка" массива
	 * @param mixed $related_value Значение ключа
	 * @param mixed $key Ключ элемента в найденном массиве, значение которого нужно получить
	 * @return mixed
	 */
	public static function select_related_cell(array $array, $related_key, $related_value, $key)
	{
		if (is_array($array) AND ! empty($array))
		{
			$array = Arr::select($array, $related_key, $related_value);
			$array = @reset($array);
			//echo Builder::debug($array);
			if ( ! empty($array))
			{
				$value = (isset($array[$key])) ? $array[$key] : NULL;
				return $value;
			}

			return NULL;
		}

		return NULL;
	}

	/**
	 * Преобразование многомерного массива в одномерный в виде "списка".
	 *
	 * ПРИМЕР ИСПОЛЬЗОВАНИЯ
	 *
	 * Имеем масив $users_roles:
	 *
	 * array
	 *	 0 =>
	 *		 array
	 *			 'name' => string 'guest' (length=5)
	 *			 'permission' => string 'view' (length=4)
	 *	 1 =>
	 *		 array
	 *			'name' => string 'user' (length=4)
	 *			'permission' => string 'view' (length=4)
	 *	 2 =>
	 *		 array
	 *			 'name' => string 'admin' (length=5)
	 *			 'permission' => null
	 *
	 * В результате $users_roles = Arr::select_list($users_roles) получим одномерный массив:
	 *
	 * array
	 *	 'guest' => string 'view' (length=4)
	 *	 'user' => string 'view' (length=4)
	 *	 'admin' => null
	 */
	public static function select_list($array, $key_col = FALSE, $value_col = FALSE)
	{
		$result = array();

		if ( ! empty($array) AND is_array($array))
		{
			if ($key_col !== FALSE AND $value_col !== FALSE)
			{
				foreach ($array as $row)
				{
					if ( ! empty($row) AND is_array($row))
					{
						$result[$row[$key_col]] = $row[$value_col];
					}
				}
			}
			else
			{
				foreach ($array as $row)
				{
					if ( ! empty($row) AND is_array($row))
					{
						$result[reset($row)] = end($row);
					}
				}
			}
		}

		return $result;
	}

	/**
	 * Преобразование многомерного массива в одномерный в виде "списка",
	 * но в качестве значений используются массивы.
	 *
	 * ПРИМЕР ИСПОЛЬЗОВАНИЯ
	 *
	 * Имеем масив $users_roles:
	 *
	 * array
	 *	 0 =>
	 *		 array
	 *			 'name' => string 'guest' (length=5)
	 *			 'permission' => string 'view' (length=4)
	 *	 1 =>
	 *		 array
	 *			 'name' => string 'user' (length=4)
	 *			 'permission' => string 'comment_articles' (length=16)
	 *	 2 =>
	 *		 array
	 *			'name' => string 'user' (length=4)
	 *			 'permission' => string 'view' (length=4)
	 *	 3 =>
	 *		 array
	 *			'name' => string 'admin' (length=5)
	 *			'permission' => null
	 *
	 *
	 * В результате $users_roles = Arr::select_list_array($users_roles) получим массив:
	 *
	 * array
	 *	 'guest' =>
	 *		 array
	 *			 0 => string 'view' (length=4)
	 *	 'user' =>
	 *		 array
	 *			 0 => string 'comment_articles' (length=16)
	 *			 1 => string 'view' (length=4)
	 *	 'admin' =>
	 *		 array
	 *			 0 => null
	 */
	public static function select_list_array($array)
	{
		$result = array();

		if ( ! empty($array) AND is_array($array))
		{
			foreach ($array as $row)
			{
				if ( ! empty($row) AND is_array($row))
				{
					$result[reset($row)][] = end($row);
				}
			}
		}

		return $result;
	}

	/**
	 * Выборка значений массива по префиксу значений.
	 *
	 * Например:
	 *
	 * Array
	 * (
	 *		 [0] => backend_access
	 *		 [1] => frontend_109
	 *		 [2] => section_templates
	 *		 [3] => frontend_110
	 * )
	 *
	 * Arr::select_by_prefix([arr], '_frontend') получит:
	 *
	 * Array
	 * (
	 *		 [0] => frontend_109
	 *		 [1] => frontend_110
	 * )
	 *
	 * @param array $array
	 * @param string $prefix
	 * @return array
	 */
	public function select_by_prefix($array, $prefix)
	{
		$result = array();

		if ( ! empty($array) AND is_array($array))
		{
			foreach ($array as $key => $row)
			{
				if (is_array($row))
					$array[$key] = Arr::select_by_prefix($row, $prefix);
				elseif (UTF8::substr($row, 0, UTF8::strlen($prefix)) == $prefix)
					$result[] = $row;
			}
		}

		return $result;
	}
	
	/**
	 * Rotates a 2D array clockwise.
	 * Example, turns a 2x3 array into a 3x2 array.
	 *
	 * @param	 array		array to rotate
	 * @param	 boolean	keep the keys in the final rotated array. the sub arrays of the source array need to have the same key values.
	 *									 if your subkeys might not match, you need to pass FALSE here!
	 * @return	array
	 */
	public static function rotate($source_array, $keep_keys = TRUE)
	{
		$new_array = array();

		foreach ($source_array as $key => $value)
		{
			$value = ($keep_keys === TRUE) ? $value : array_values($value);

			foreach ($value as $k => $v)
			{
				$new_array[$k][$key] = $v;
			}
		}

		return $new_array;
	}
	
	/**
	 * Removes a key from an array and returns the value.
	 *
	 * @param	 string	key to return
	 * @param	 array	 array to work on
	 * @return	mixed	 value of the requested array key
	 */
	public static function remove($key, & $array)
	{
		if (!array_key_exists($key, $array))
			return NULL;

		$val = $array[$key];
		unset($array[$key]);

		return $val;
	}
	
	/**
	 * Because PHP does not have this function.
	 *
	 * @param	 array	 array to unshift
	 * @param	 string	key to unshift
	 * @param	 mixed	 value to unshift
	 * @return	array
	 */
	public static function unshift_assoc(array & $array, $key, $val)
	{
		$array = array_reverse($array, TRUE);
		$array[$key] = $val;
		$array = array_reverse($array, TRUE);

		return $array;
	}
	
	/**
	 * Because PHP does not have this function, and array_walk_recursive creates
	 * references in arrays and is not truly recursive.
	 *
	 * @param	 mixed	callback to apply to each member of the array
	 * @param	 array	array to map to
	 * @return	array
	 */
	public static function map_recursive($callback, array $array)
	{
		foreach ($array as $key => $val)
		{
			// Map the callback to the key
			$array[$key] = is_array($val) ? Arr::map_recursive($callback, $val) : call_user_func($callback, $val);
		}

		return $array;
	}
	
	/**
	 * @param mixed $needle		 the value to search for
	 * @param array $haystack	 an array of values to search in
	 * @param boolean $sort		 sort the array now
	 * @return integer|FALSE		the index of the match or FALSE when not found
	 */
	public static function binary_search($needle, $haystack, $sort = FALSE)
	{
		if ($sort)
		{
			sort($haystack);
		}

		$high = count($haystack) - 1;
		$low = 0;

		while ($low <= $high)
		{
			$mid = ($low + $high) >> 1;

			if ($haystack[$mid] < $needle)
			{
				$low = $mid + 1;
			}
			elseif ($haystack[$mid] > $needle)
			{
				$high = $mid - 1;
			}
			else
			{
				return $mid;
			}
		}

		return FALSE;
	}
	
	/**
	 * Recursively convert an array to an object.
	 *
	 * @param	 array	 array to convert
	 * @return	object
	 */
	public static function to_object(array $array, $class = 'stdClass')
	{
		$object = new $class;

		foreach ($array as $key => $value)
		{
			if (is_array($value))
			{
				// Convert the array to an object
				$value = Arr::to_object($value, $class);
			}

			// Add the value to the object
			$object->{$key} = $value;
		}

		return $object;
	}

	/**
	 * Рекурсивное конвертирование объекта в массив (так как (array) $obj конвертирует только верхний уровень).
	 *
	 * @param object $object
	 * @return array
	 */
	public static function from_object($object)
	{
		if ( ! is_object($object) AND !is_array($object))
		{
			return $object;
		}
		if (is_object($object))
		{
			$object = get_object_vars($object);
		}

		return array_map(array('Arr', 'from_object'), $object);
	}
	
	/**
	 * Получение данных в массив из объекта(ов) ORM.
	 * 
	 * @param	array|object	$objects 
	 */
	public static function from_orm($objects)
	{
		if (is_array($objects) AND ! empty($objects))
		{
			foreach ($objects as $key => $object)
			{
				if ($object instanceOf ORM)
				{
					$objects[$key] = $object->as_array();
				}
			}
		}
		elseif ($objects instanceOf ORM)
		{
			$objects = $object->as_array();
			$objects = Arr::from_orm($objects);
		}
		
		return $objects;
	}
	
	/**
	 * Сортировка много мерного массива по полю.
	 */
	public static function orderby($data, $field, $condition = 'ASC')
	{
		$code = "return strnatcmp(\$a['$field'], \$b['$field']);";
		usort($data, create_function('$a,$b', $code));
		return $condition == 'ASC' ? $data : array_reverse($data);
	}
	
	/**
	 * Преобразование массива в строковое представление для дальнейшего eval
	 */
	public static function to_string($array)
	{
		$code = ' array(';
		if (is_array($array))
		{
			$subcode = array();
			foreach ($array as $key => $value)
			{
				$subcode[] = '\''.$key.'\' => '.(is_array($value) ? Arr::to_string($value) : '\''.$value.'\'');
			}
			$code .= implode(",",$subcode);
		}
		else
		{
			$code .= '\''.$array.'\'';
		}
		$code .= ')';

		return $code;
	}

	/**
	 * Преобразование массива в список аргументов (для элементов первого уровня) для дальнейшего eval
	 */
	public static function to_arg_string($array)
	{
		$code = '';
		if (is_array($array))
		{
			foreach ($array as $key => $value)
			{
				$code .= (is_array($value) ? Arr::to_string($value) : '\''.$value.'\'');
				if (isset($array[$key + 1]))
					$code .= ', ';
			}
		}
		else
		{
			$code .= '\''.$array.'\'';
		}

		return $code;
	}
	
}